#include "Display_EPD_W21_spi.h"
#include "Display_EPD_W21.h"

#ifndef EPD_37

#define Source_BITS 240
#define Gate_BITS 416
#define ALLSCREEN_BYTES Source_BITS *Gate_BITS / 4

// Delay Functions
void delay_xms(unsigned int xms)
{
	unsigned int i;
	while (xms--)
	{
		i = 12000;
		while (i--)
			;
	}
}

////////////////////////////////////E-paper demo//////////////////////////////////////////////////////////
// Busy function
void Epaper_READBUSY(void)
{
	while (1)
	{ //=1 BUSY
		if (epd_is_busy() == 0)
			break;
	}
}

void lcd_chkstatus(void)
{
	while (1)
	{ //=0 BUSY
		if (isEPD_W21_BUSY == 1)
			break;
	}
}

// Full screen update initialization
void EPD_HW_Init(void)
{
	delay_xms(100); // At least 100ms delay
	EPD_W21_RST_0;	// Module reset
	delay_xms(50);	// At least 50ms delay
	EPD_W21_RST_1;
	delay_xms(50);	 // At least 50ms delay
	lcd_chkstatus(); // waiting for the electronic paper IC to release the idle signal

	EPD_W21_WriteCMD(0x00); // 0x00
	EPD_W21_WriteDATA(0x0F);
	EPD_W21_WriteDATA(0x29);

	EPD_W21_WriteCMD(0x01); // 0x01
	EPD_W21_WriteDATA(0x07);
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x22); // RED
	EPD_W21_WriteDATA(0x78);
	EPD_W21_WriteDATA(0x0A); // WHITE
	EPD_W21_WriteDATA(0x22); // RED

	EPD_W21_WriteCMD(0x03); // 0x03
	EPD_W21_WriteDATA(0x10);
	EPD_W21_WriteDATA(0x54);
	EPD_W21_WriteDATA(0x44);

	EPD_W21_WriteCMD(0x06); // 0x06
	EPD_W21_WriteDATA(0xC0);
	EPD_W21_WriteDATA(0xC0);
	EPD_W21_WriteDATA(0xC0);

	EPD_W21_WriteCMD(0x30); // 0x30
	EPD_W21_WriteDATA(0x08);

	EPD_W21_WriteCMD(0x41); // 0x41
	EPD_W21_WriteDATA(0x00);

	EPD_W21_WriteCMD(0x50); // 0x50
	EPD_W21_WriteDATA(0x37);

	EPD_W21_WriteCMD(0x60); // 0x60
	EPD_W21_WriteDATA(0x02);
	EPD_W21_WriteDATA(0x02);

	EPD_W21_WriteCMD(0x61); // 0x61
	EPD_W21_WriteDATA(Source_BITS / 256);
	EPD_W21_WriteDATA(Source_BITS % 256);
	EPD_W21_WriteDATA(Gate_BITS / 256);
	EPD_W21_WriteDATA(Gate_BITS % 256);

	EPD_W21_WriteCMD(0x65); // 0x65
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x00);

	EPD_W21_WriteCMD(0xE7); // 0xE7
	EPD_W21_WriteDATA(0x1C);

	EPD_W21_WriteCMD(0xE3); // 0xE3
	EPD_W21_WriteDATA(0x22);
	/*
		EPD_W21_WriteCMD(0xE0);	//0xE0
		EPD_W21_WriteDATA(0x00);	*/

	EPD_W21_WriteCMD(0xFF);	 // Enter
	EPD_W21_WriteDATA(0xA5); // Enter

	EPD_W21_WriteCMD(0xEF); // PWM
	EPD_W21_WriteDATA(0x01);
	EPD_W21_WriteDATA(0x1E);
	EPD_W21_WriteDATA(0x0A);
	EPD_W21_WriteDATA(0x1B);
	EPD_W21_WriteDATA(0x0B);
	EPD_W21_WriteDATA(0x17);

	EPD_W21_WriteCMD(0xC3); // PWM
	EPD_W21_WriteDATA(0xFD);
	EPD_W21_WriteCMD(0xDC); // CPCK
	EPD_W21_WriteDATA(0x01);
	EPD_W21_WriteCMD(0xDD);
	EPD_W21_WriteDATA(0x08);
	EPD_W21_WriteCMD(0xDE);
	EPD_W21_WriteDATA(0x41);

	EPD_W21_WriteCMD(0xFD); // VDLOS
	EPD_W21_WriteDATA(0x01);
	EPD_W21_WriteCMD(0xE8);
	EPD_W21_WriteDATA(0x03);

	EPD_W21_WriteCMD(0xDA); // DAh
	EPD_W21_WriteDATA(0x07);

	EPD_W21_WriteCMD(0xC9); // GDR
	EPD_W21_WriteDATA(0x00);

	EPD_W21_WriteCMD(0xA8); // VDH
	EPD_W21_WriteDATA(0x0F);

	EPD_W21_WriteCMD(0xFF);
	EPD_W21_WriteDATA(0xE3); // Exit

	EPD_W21_WriteCMD(0xE9);
	EPD_W21_WriteDATA(0x01);

	EPD_W21_WriteCMD(0x04); // Power on
	lcd_chkstatus();		// waiting for the electronic paper IC to release the idle signal

	EPD_W21_WriteCMD(0xFF);
	EPD_W21_WriteDATA(0xA5);

	EPD_W21_WriteCMD(0xEF);
	EPD_W21_WriteDATA(0x03);
	EPD_W21_WriteDATA(0x1E);
	EPD_W21_WriteDATA(0x0A);
	EPD_W21_WriteDATA(0x1B);
	EPD_W21_WriteDATA(0x0E);
	EPD_W21_WriteDATA(0x15);

	EPD_W21_WriteCMD(0xDC);
	EPD_W21_WriteDATA(0x01);

	EPD_W21_WriteCMD(0xDD);
	EPD_W21_WriteDATA(0x08);

	EPD_W21_WriteCMD(0xDE);
	EPD_W21_WriteDATA(0x41);

	EPD_W21_WriteCMD(0xFF);
	EPD_W21_WriteDATA(0xE3);
}
// Fast full screen update initialization
void EPD_HW_Init_Fast(void) // 1.6s
{
	epd_res_reset(); // Module reset
	delay_xms(10);	 // At least 10ms delay
	epd_res_set();
	delay_xms(10); // At least 10ms delay

	EPD_W21_WriteCMD(0X00);	 // PANNEL SETTING
	EPD_W21_WriteDATA(0x0F); // KW-3f   KWR-2F	BWROTP 0f	BWOTP 1f

	EPD_W21_WriteCMD(0x04); // POWER ON
	delay_xms(100);
	Epaper_READBUSY(); // waiting for the electronic paper IC to release the idle signal

	// Enhanced display drive(Add 0x06 command)
	EPD_W21_WriteCMD(0x06); // Booster Soft Start
	EPD_W21_WriteDATA(0x27);
	EPD_W21_WriteDATA(0x27);
	EPD_W21_WriteDATA(0x18);
	EPD_W21_WriteDATA(0x17);

	EPD_W21_WriteCMD(0xE0);
	EPD_W21_WriteDATA(0x02);
	EPD_W21_WriteCMD(0xE5);
	EPD_W21_WriteDATA(0x5A);

	EPD_W21_WriteCMD(0X50); // VCOM AND DATA INTERVAL SETTING
	EPD_W21_WriteDATA(0x11);
	EPD_W21_WriteDATA(0x07);
}
//////////////////////////////Display Update Function///////////////////////////////////////////////////////
// Full screen update function
void EPD_Update(void)
{
	EPD_W21_WriteCMD(0x22); // Display Update Control
	EPD_W21_WriteDATA(0xF7);
	EPD_W21_WriteCMD(0x20); // Activate Display Update Sequence
	Epaper_READBUSY();
}
// Fast full screen  update function
void EPD_Update_Fast(void)
{
	EPD_W21_WriteCMD(0x22); // Display Update Control
	EPD_W21_WriteDATA(0xC7);
	EPD_W21_WriteCMD(0x20); // Activate Display Update Sequence
	Epaper_READBUSY();
}
// Full screen  update function (Basemap)
void EPD_Update_BaseMap(void)
{
	EPD_W21_WriteCMD(0x22); // Display Update Control
	EPD_W21_WriteDATA(0xF4);
	EPD_W21_WriteCMD(0x20); // Activate Display Update Sequence
	Epaper_READBUSY();
}
// Partial update function
void EPD_Part_Update(void)
{
	EPD_W21_WriteCMD(0x22); // Display Update Control
	EPD_W21_WriteDATA(0x1C);
	EPD_W21_WriteCMD(0x20); // Activate Display Update Sequence
	Epaper_READBUSY();
}
//////////////////////////////Display Data Transfer Function////////////////////////////////////////////
// Full screen update display function
void EPD_WhiteScreen_ALL(const unsigned char *datasBW, const unsigned char *datasRW)
{
	unsigned int i;
	// Write Data
	EPD_W21_WriteCMD(0x24); // Transfer old data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(datasBW[i]); // Transfer the actual displayed data
	}
	EPD_W21_WriteCMD(0x26); // Transfer new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(~datasRW[i]); // Transfer the actual displayed data
	}
	EPD_Update();
}
// Fast full screen update display function
void EPD_WhiteScreen_ALL_Fast(const unsigned char *datasBW, const unsigned char *datasRW)
{
	unsigned int i;
	// Write Data
	EPD_W21_WriteCMD(0x24); // Transfer old data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(datasBW[i]); // Transfer the actual displayed data
	}
	EPD_W21_WriteCMD(0x26); // Transfer new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(~datasRW[i]); // Transfer the actual displayed data
	}
	EPD_Update_Fast();
}
// Clear screen display
void EPD_WhiteScreen_White(void)
{
	unsigned int i;
	// Write Data
	EPD_W21_WriteCMD(0x24); // Transfer old data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(0xFF);
	}
	EPD_W21_WriteCMD(0x26); // Transfer new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(0x00); // Transfer the actual displayed data
	}
	EPD_Update();
}
// Clear screen display
void EPD_WhiteScreen_White_Fast(void)
{
	unsigned int i;

	EPD_W21_WriteCMD(0x3c);	 // set border
	EPD_W21_WriteDATA(0x01); // 0x00=black ?? 0x01=white ?? 0x80=VCOM ?? 0xc0=HiZ??default??
							 // Write Data
	EPD_W21_WriteCMD(0x24);	 // Transfer old data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(0xFF);
	}
	EPD_W21_WriteCMD(0x26); // Transfer new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(0x00); // Transfer the actual displayed data
	}
	EPD_Update_Fast();

	EPD_W21_WriteCMD(0x26); // Transfer new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(0xFF); // Transfer the actual displayed data
	}
}
// Display all black
void EPD_WhiteScreen_Black(void)
{
	unsigned int i;
	// Write Data
	EPD_W21_WriteCMD(0x24); // Transfer old data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(0x00);
	}
	EPD_W21_WriteCMD(0x26); // Transfer new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(0x00); // Transfer the actual displayed data
	}
	EPD_Update();
}

// Partial update of background display, this function is necessary, please do not delete it!!!
void EPD_SetRAMValue_BaseMap(const unsigned char *datasBW, const unsigned char *datasRW)
{
	unsigned int i;
	unsigned char a;
	// Write Data
	EPD_W21_WriteCMD(0x24); // Transfer old data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(datasBW[i]); // Transfer the actual displayed data
	}
	EPD_W21_WriteCMD(0x26); // Transfer new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(~datasRW[i]); // Transfer the actual displayed data
	}
	EPD_Update_BaseMap();
	Epaper_READBUSY();

	// Write Data??update??
	EPD_W21_WriteCMD(0x24); // Transfer old data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		a = datasBW[i] & datasRW[i];
		EPD_W21_WriteDATA(a); // Transfer the actual displayed data
	}
	EPD_W21_WriteCMD(0x26); // Transfer new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		a = datasBW[i] & datasRW[i];
		EPD_W21_WriteDATA(a); // Transfer the actual displayed data
	}

	//////////////////////////////////////////////
}
// Partial update display
void EPD_Dis_Part(unsigned int x_start, unsigned int y_start, const unsigned char *datas, unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	unsigned int i;
	unsigned int x_end, y_end;

	x_start = x_start / 8;				 // x address start
	x_end = x_start + PART_LINE / 8 - 1; // x address end
	y_start = y_start;					 // Y address start
	y_end = y_start + PART_COLUMN - 1;	 // Y address end
	/*
	EPD_W21_RST_0;  // Module reset
	delay_xms(10);//At least 10ms delay
	EPD_W21_RST_1;
	delay_xms(10); //At least 10ms delay

	EPD_W21_WriteCMD(0x3C); //set border to vcom
	EPD_W21_WriteDATA(0x80);
	*/
	EPD_W21_WriteCMD(0x44);			  // set RAM x address start/end
	EPD_W21_WriteDATA(x_start);		  // x address start
	EPD_W21_WriteDATA(x_end);		  // y address end
	EPD_W21_WriteCMD(0x45);			  // set RAM y address start/end
	EPD_W21_WriteDATA(y_start % 256); // y address start2
	EPD_W21_WriteDATA(y_start / 256); // y address start1
	EPD_W21_WriteDATA(y_end % 256);	  // y address end2
	EPD_W21_WriteDATA(y_end / 256);	  // y address end1

	EPD_W21_WriteCMD(0x4E);			  // set RAM x address count to 0;
	EPD_W21_WriteDATA(x_start);		  // x start address
	EPD_W21_WriteCMD(0x4F);			  // set RAM y address count to 0X127;
	EPD_W21_WriteDATA(y_start % 256); // y address start2
	EPD_W21_WriteDATA(y_start / 256); // y address start1

	EPD_W21_WriteCMD(0x24); // Write Black and White image to RAM
	for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
	{
		EPD_W21_WriteDATA(datas[i]);
	}
	EPD_Part_Update();
}

// Deep sleep function
void EPD_DeepSleep(void)
{
	EPD_W21_WriteCMD(0x02); // Enter deep sleep
	EPD_W21_WriteDATA(0x00);
	delay_xms(100); //!!!The delay here is necessary,100mS at least!!!

	EPD_W21_WriteCMD(0X07); // deep sleep
	EPD_W21_WriteDATA(0xA5);
}

// Partial update write address and data
void EPD_Dis_Part_RAM(unsigned int x_start, unsigned int y_start, const unsigned char *datas, unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	unsigned int i;
	unsigned int x_end, y_end;

	x_start = x_start / 8;				 // x address start
	x_end = x_start + PART_LINE / 8 - 1; // x address end

	y_start = y_start - 1;			   // Y address start
	y_end = y_start + PART_COLUMN - 1; // Y address end

	EPD_W21_WriteCMD(0x44);			  // set RAM x address start/end
	EPD_W21_WriteDATA(x_start);		  // x address start
	EPD_W21_WriteDATA(x_end);		  // y address end
	EPD_W21_WriteCMD(0x45);			  // set RAM y address start/end
	EPD_W21_WriteDATA(y_start % 256); // y address start2
	EPD_W21_WriteDATA(y_start / 256); // y address start1
	EPD_W21_WriteDATA(y_end % 256);	  // y address end2
	EPD_W21_WriteDATA(y_end / 256);	  // y address end1

	EPD_W21_WriteCMD(0x4E);			  // set RAM x address count to 0;
	EPD_W21_WriteDATA(x_start);		  // x start address
	EPD_W21_WriteCMD(0x4F);			  // set RAM y address count to 0X127;
	EPD_W21_WriteDATA(y_start % 256); // y address start2
	EPD_W21_WriteDATA(y_start / 256); // y address start1

	EPD_W21_WriteCMD(0x24); // Write Black and White image to RAM
	for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
	{
		EPD_W21_WriteDATA(datas[i]);
	}
}
// Num display
void EPD_Dis_Part_Num(unsigned int x_startA, unsigned int y_startA, const unsigned char *datasA,
					  unsigned int x_startB, unsigned int y_startB, const unsigned char *datasB,
					  unsigned int x_startC, unsigned int y_startC, const unsigned char *datasC,
					  unsigned int x_startD, unsigned int y_startD, const unsigned char *datasD,
					  unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	EPD_Dis_Part_RAM(x_startA, y_startA, datasA, PART_COLUMN, PART_LINE);
	EPD_Dis_Part_RAM(x_startB, y_startB, datasB, PART_COLUMN, PART_LINE);
	EPD_Dis_Part_RAM(x_startC, y_startC, datasC, PART_COLUMN, PART_LINE);
	EPD_Dis_Part_RAM(x_startD, y_startD, datasD, PART_COLUMN, PART_LINE);
	EPD_Part_Update();
}

////////////////////////////////Other newly added functions////////////////////////////////////////////
// Display rotation 180 degrees initialization
void EPD_HW_Init_180(void)
{
	epd_res_reset(); // Module reset
	delay_xms(10);	 // At least 10ms delay
	epd_res_set();
	delay_xms(10); // At least 10ms delay

	Epaper_READBUSY();
	EPD_W21_WriteCMD(0x12); // SWRESET
	Epaper_READBUSY();

	EPD_W21_WriteCMD(0x3C); // BorderWavefrom
	EPD_W21_WriteDATA(0x05);

	EPD_W21_WriteCMD(0x01); // Driver output control
	EPD_W21_WriteDATA((EPD_HEIGHT - 1) % 256);
	EPD_W21_WriteDATA((EPD_HEIGHT - 1) / 256);
	EPD_W21_WriteDATA(0x00);

	EPD_W21_WriteCMD(0x11); // data entry mode
	EPD_W21_WriteDATA(0x02);

	EPD_W21_WriteCMD(0x44); // set Ram-X address start/end position
	EPD_W21_WriteDATA(EPD_WIDTH / 8 - 1);
	EPD_W21_WriteDATA(0x00);

	EPD_W21_WriteCMD(0x45); // set Ram-Y address start/end position
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA((EPD_HEIGHT - 1) % 256);
	EPD_W21_WriteDATA((EPD_HEIGHT - 1) / 256);

	EPD_W21_WriteCMD(0x18); // Read built-in temperature sensor
	EPD_W21_WriteDATA(0x80);

	EPD_W21_WriteCMD(0x4E); // set RAM x address count to 0;
	EPD_W21_WriteDATA(EPD_WIDTH / 8 - 1);
	EPD_W21_WriteCMD(0x4F); // set RAM y address count to 0X199;
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x00);
	Epaper_READBUSY();
}
// GUI initialization
void EPD_HW_Init_GUI(void)
{
	delay_xms(100);	 // At least 100ms delay
	epd_res_reset(); // Module reset
	delay_xms(100);	 // At least 10ms delay
	epd_res_set();
	delay_xms(100); // At least 10ms delay
#if 0
	Epaper_READBUSY();
	EPD_W21_WriteCMD(0x12); // SWRESET
	Epaper_READBUSY();

	EPD_W21_WriteCMD(0x01); // Driver output control
	EPD_W21_WriteDATA((EPD_HEIGHT + 46 - 1) % 256);
	EPD_W21_WriteDATA((EPD_HEIGHT + 46 - 1) / 256);
	EPD_W21_WriteDATA(0x01); // Show mirror

	EPD_W21_WriteCMD(0x11); // data entry mode
	EPD_W21_WriteDATA(0x01);

	EPD_W21_WriteCMD(0x44); // set Ram-X address start/end position
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(EPD_WIDTH / 8 - 1);

	EPD_W21_WriteCMD(0x45); // set Ram-Y address start/end position
	EPD_W21_WriteDATA((EPD_HEIGHT + 46 - 1) % 256);
	EPD_W21_WriteDATA((EPD_HEIGHT + 46 - 1) / 256);
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x00);

	EPD_W21_WriteCMD(0x3C); // BorderWavefrom
	EPD_W21_WriteDATA(0x05);

	EPD_W21_WriteCMD(0x18); // Read built-in temperature sensor
	EPD_W21_WriteDATA(0x80);

	EPD_W21_WriteCMD(0x4E); // set RAM x address count to 0;
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteCMD(0x4F); // set RAM y address count to 0X199;
	EPD_W21_WriteDATA((EPD_HEIGHT + 46 - 1) % 256);
	EPD_W21_WriteDATA((EPD_HEIGHT + 46 - 1) / 256);
	Epaper_READBUSY();
#endif

#if 1
	Epaper_READBUSY();
	EPD_W21_WriteCMD(0x00);
	EPD_W21_WriteDATA(0x0F);
	EPD_W21_WriteDATA(0x29);

	EPD_W21_WriteCMD(0x01); // 0x01
	EPD_W21_WriteDATA(0x07);
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x22); // RED
	EPD_W21_WriteDATA(0x78);
	EPD_W21_WriteDATA(0x0A); // WHITE
	EPD_W21_WriteDATA(0x22); // RED

	EPD_W21_WriteCMD(0x03); // 0x03
	EPD_W21_WriteDATA(0x10);
	EPD_W21_WriteDATA(0x54);
	EPD_W21_WriteDATA(0x44);

	EPD_W21_WriteCMD(0x06); // 0x06
	EPD_W21_WriteDATA(0xC0);
	EPD_W21_WriteDATA(0xC0);
	EPD_W21_WriteDATA(0xC0);

	EPD_W21_WriteCMD(0x30); // 0x30
	EPD_W21_WriteDATA(0x08);

	EPD_W21_WriteCMD(0x41); // 0x41
	EPD_W21_WriteDATA(0x00);

	EPD_W21_WriteCMD(0x50); // 0x50
	EPD_W21_WriteDATA(0x37);

	EPD_W21_WriteCMD(0x60); // 0x60
	EPD_W21_WriteDATA(0x02);
	EPD_W21_WriteDATA(0x02);

	EPD_W21_WriteCMD(0x61); // 0x61
	EPD_W21_WriteDATA(EPD_HEIGHT / 256);
	EPD_W21_WriteDATA(EPD_HEIGHT % 256);
	EPD_W21_WriteDATA(EPD_WIDTH / 256);
	EPD_W21_WriteDATA(EPD_WIDTH % 256);

	EPD_W21_WriteCMD(0x65); // 0x65
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x00);
	EPD_W21_WriteDATA(0x00);

	EPD_W21_WriteCMD(0xE7); // 0xE7
	EPD_W21_WriteDATA(0x1C);

	EPD_W21_WriteCMD(0xE3); // 0xE3
	EPD_W21_WriteDATA(0x22);

	EPD_W21_WriteCMD(0xFF);	 // Enter
	EPD_W21_WriteDATA(0xA5); // Enter

	EPD_W21_WriteCMD(0xEF); // PWM
	EPD_W21_WriteDATA(0x01);
	EPD_W21_WriteDATA(0x1E);
	EPD_W21_WriteDATA(0x0A);
	EPD_W21_WriteDATA(0x1B);
	EPD_W21_WriteDATA(0x0B);
	EPD_W21_WriteDATA(0x17);

	EPD_W21_WriteCMD(0xC3); // PWM
	EPD_W21_WriteDATA(0xFD);
	EPD_W21_WriteCMD(0xDC); // CPCK
	EPD_W21_WriteDATA(0x01);
	EPD_W21_WriteCMD(0xDD);
	EPD_W21_WriteDATA(0x08);
	EPD_W21_WriteCMD(0xDE);
	EPD_W21_WriteDATA(0x41);

	EPD_W21_WriteCMD(0xFD); // VDLOS
	EPD_W21_WriteDATA(0x01);
	EPD_W21_WriteCMD(0xE8);
	EPD_W21_WriteDATA(0x03);

	EPD_W21_WriteCMD(0xDA); // DAh
	EPD_W21_WriteDATA(0x07);

	EPD_W21_WriteCMD(0xC9); // GDR
	EPD_W21_WriteDATA(0x00);

	EPD_W21_WriteCMD(0xA8); // VDH
	EPD_W21_WriteDATA(0x0F);

	EPD_W21_WriteCMD(0xFF);
	EPD_W21_WriteDATA(0xE3); // Exit

	EPD_W21_WriteCMD(0xE9);
	EPD_W21_WriteDATA(0x01);

	EPD_W21_WriteCMD(0x04); // Power on
	Epaper_READBUSY();

	EPD_W21_WriteCMD(0xFF);
	EPD_W21_WriteDATA(0xA5);

	EPD_W21_WriteCMD(0xEF);
	EPD_W21_WriteDATA(0x03);
	EPD_W21_WriteDATA(0x1E);
	EPD_W21_WriteDATA(0x0A);
	EPD_W21_WriteDATA(0x1B);
	EPD_W21_WriteDATA(0x0E);
	EPD_W21_WriteDATA(0x15);

	EPD_W21_WriteCMD(0xDC);
	EPD_W21_WriteDATA(0x01);

	EPD_W21_WriteCMD(0xDD);
	EPD_W21_WriteDATA(0x08);

	EPD_W21_WriteCMD(0xDE);
	EPD_W21_WriteDATA(0x41);

	EPD_W21_WriteCMD(0xFF);
	EPD_W21_WriteDATA(0xE3);
#endif
}

// GUI display
void EPD_Display(unsigned char *Image)
{
	unsigned int Width, Height, i, j;
	Width = (EPD_WIDTH % 8 == 0) ? (EPD_WIDTH / 8) : (EPD_WIDTH / 8 + 1);
	Height = EPD_HEIGHT;

	EPD_W21_WriteCMD(0x24);
	for (j = 0; j < Height; j++)
	{
		for (i = 0; i < Width; i++)
		{
			EPD_W21_WriteDATA(Image[i + j * Width]);
		}
	}
	EPD_Update();
}

void EPD_Display_BW(unsigned char *Image)
{
	unsigned int Width, Height, i, j;
	Width = (EPD_WIDTH % 8 == 0) ? (EPD_WIDTH / 8) : (EPD_WIDTH / 8 + 1);
	Height = EPD_HEIGHT;

	EPD_W21_WriteCMD(0x24);
	for (j = 0; j < Height; j++)
	{
		for (i = 0; i < Width; i++)
		{
			EPD_W21_WriteDATA(Image[i + j * Width]);
		}
	}

	EPD_Update();
}

void EPD_Display_R(unsigned char *Image)
{
	unsigned int Width, Height, i, j;
	Width = (EPD_WIDTH % 8 == 0) ? (EPD_WIDTH / 8) : (EPD_WIDTH / 8 + 1);
	Height = EPD_HEIGHT;

	EPD_W21_WriteCMD(0x26);
	for (j = 0; j < Height; j++)
	{
		for (i = 0; i < Width; i++)
		{
			EPD_W21_WriteDATA(Image[i + j * Width]);
		}
	}

	EPD_Update();
}

void EPD_refresh(void)
{
	EPD_W21_WriteCMD(0x12); // Display Update Control
	EPD_W21_WriteDATA(0x00);
	lcd_chkstatus();
}

void Display_All_Yellow(void)
{
	unsigned long i;

	EPD_W21_WriteCMD(0x10);
	{
		for (i = 0; i < ALLSCREEN_BYTES; i++)
		{
			EPD_W21_WriteDATA(0xaa);
		}
	}
	EPD_refresh();
}

// 2bit
#define black 0x00	/// 00
#define white 0x01	///	01
#define yellow 0x02 ///	10
#define red 0x03	///	11

unsigned char Color_get(unsigned char color)
{
	unsigned datas;
	switch (color)
	{
	case 0x00:
		datas = white;
		break;
	case 0x01:
		datas = yellow;
		break;
	case 0x02:
		datas = red;
		break;
	case 0x03:
		datas = black;
		break;
	default:
		break;
	}
	return datas;
}

void PIC_display(const unsigned char *picData)
{
	unsigned int i, j;
	unsigned char temp1;
	unsigned char data_H1, data_H2, data_L1, data_L2, data;

	EPD_W21_WriteCMD(0x10);
	for (i = 0; i < Gate_BITS; i++) // Source_BITS*Gate_BITS/4
	{
		for (j = 0; j < Source_BITS / 4; j++)
		{
			temp1 = picData[i * Source_BITS / 4 + j];

			data_H1 = Color_get(temp1 >> 6 & 0x03) << 6;
			data_H2 = Color_get(temp1 >> 4 & 0x03) << 4;
			data_L1 = Color_get(temp1 >> 2 & 0x03) << 2;
			data_L2 = Color_get(temp1 & 0x03);

			data = data_H1 | data_H2 | data_L1 | data_L2;
			EPD_W21_WriteDATA(data);
		}
	}

	// Refresh
	EPD_refresh();
}

#endif

#ifdef EPD_37

unsigned char oldData[12480];
unsigned char oldDataP[256];
unsigned char oldDataA[256];
unsigned char oldDataB[256];
unsigned char oldDataA2[256];
unsigned char oldDataB2[256];
unsigned char oldDataC[256];
unsigned char oldDataD[256];
unsigned char oldDataE[256];
unsigned char partFlag = 1;
unsigned char partFlag2 = 1;
void delay_xms(unsigned int xms)
{
	unsigned int i;
	while (xms--)
	{
		i = 12000;
		while (i--)
			;
	}
}

void lcd_chkstatus(void)
{
	while (!isEPD_W21_BUSY)
		; // 0:BUSY, 1:FREE
}

// UC8253
void EPD_Init(void)
{
	EPD_W21_RST_0; // Module reset
	delay_xms(10); // At least 10ms delay
	EPD_W21_RST_1;
	delay_xms(10); // At least 10ms delay

	EPD_W21_WriteCMD(0x04); // Power on
	lcd_chkstatus();		// waiting for the electronic paper IC to release the idle signal
}
void EPD_Init_Fast(void) // 16s
{
	EPD_W21_RST_0; // Module reset
	delay_xms(10); // At least 10ms delay
	EPD_W21_RST_1;
	delay_xms(10); // At least 10ms delay

	EPD_W21_WriteCMD(0x04); // Power on
	lcd_chkstatus();		// waiting for the electronic paper IC to release the idle signal

	EPD_W21_WriteCMD(0xE0);
	EPD_W21_WriteDATA(0x02);

	EPD_W21_WriteCMD(0xE5);
	EPD_W21_WriteDATA(0x5A);
}

void EPD_Init_Part(void)
{
	EPD_W21_RST_0; // Module reset
	delay_xms(10); // At least 10ms delay
	EPD_W21_RST_1;
	delay_xms(10); // At least 10ms delay

	EPD_W21_WriteCMD(0x00);	 // panel setting
	EPD_W21_WriteDATA(0xd7); // RES[1:0], REG, KW/R, UD, SHL, SHD_N, RST_N          LUT_REG

	EPD_W21_WriteCMD(0x04); // Power on
	lcd_chkstatus();		// waiting for the electronic paper IC to release the idle signal

	EPD_W21_WriteCMD(0xE0);
	EPD_W21_WriteDATA(0x02);

	EPD_W21_WriteCMD(0xE5);
	EPD_W21_WriteDATA(0x6E);

	EPD_W21_WriteCMD(0X50);	 // VCOM AND DATA INTERVAL SETTING
	EPD_W21_WriteDATA(0x97); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57		WBRmode:VBDF F7 VBDW 77 VBDB 37  VBDR B7
}
void EPD_DeepSleep(void)
{
	EPD_W21_WriteCMD(0X02); // power off
	lcd_chkstatus();		// waiting for the electronic paper IC to release the idle signal
	delay_xms(100);			// At least 100ms delay
	EPD_W21_WriteCMD(0X07); // deep sleep
	EPD_W21_WriteDATA(0xA5);
}
void Power_off(void)
{
	EPD_W21_WriteCMD(0x02); // POWER ON
	lcd_chkstatus();
}
// Full screen refresh update function
void EPD_Update(void)
{
	// Refresh
	EPD_W21_WriteCMD(0x12); // DISPLAY REFRESH
	delay_xms(1);			//!!!The delay here is necessary, 200uS at least!!!
	lcd_chkstatus();		// waiting for the electronic paper IC to release the idle signal
}
void EPD_WhiteScreen_ALL(const unsigned char *datasBW, const unsigned char *datasRW)
{
	unsigned int i;
	// Write Data
	EPD_W21_WriteCMD(0x10); // Transfer old data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(datasBW[i]); // Transfer the actual displayed data
	}
	EPD_W21_WriteCMD(0x13); // Transfer new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(~datasRW[i]); // Transfer the actual displayed data
	}
	EPD_Update();
}

// Clear screen display
void EPD_WhiteScreen_White(void)
{
	unsigned int i;
	// Write Data
	EPD_W21_WriteCMD(0x10);
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(0xFF);
	}
	EPD_W21_WriteCMD(0x13);
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(0x00);
	}
	EPD_Update();
	Power_off();
}

// Partial refresh of background display, this function is necessary, please do not delete it!!!
void EPD_SetRAMValue_BaseMap(const unsigned char *datasBW, const unsigned char *datasRW)
{
	unsigned int i;
	EPD_W21_WriteCMD(0x10); // write old data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(datasBW[i]);
	}
	EPD_W21_WriteCMD(0x13); // write new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(~datasRW[i]);
	}
	EPD_Update();
	EPD_W21_WriteCMD(0x13); // write new data
	for (i = 0; i < EPD_ARRAY; i++)
	{
		EPD_W21_WriteDATA(datasBW[i]);
	}
}
void EPD_Dis_Part(unsigned int x_start, unsigned int y_start, const unsigned char *datas, unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	unsigned int i;
	unsigned int x_end, y_end;
	x_start = x_start - x_start % 8;
	x_end = x_start + PART_LINE - 1;
	y_end = y_start + PART_COLUMN - 1;

	EPD_Init_Part();

	EPD_W21_WriteCMD(0x91);		// This command makes the display enter partial mode
	EPD_W21_WriteCMD(0x90);		// resolution setting
	EPD_W21_WriteDATA(x_start); // x-start
	EPD_W21_WriteDATA(x_end);	// x-end

	EPD_W21_WriteDATA(y_start / 256);
	EPD_W21_WriteDATA(y_start % 256); // y-start

	EPD_W21_WriteDATA(y_end / 256);
	EPD_W21_WriteDATA(y_end % 256); // y-end
	EPD_W21_WriteDATA(0x01);

	if (partFlag == 1)
	{
		partFlag = 0;

		EPD_W21_WriteCMD(0x10); // writes Old data to SRAM for programming
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(0xFF);
	}
	else
	{
		EPD_W21_WriteCMD(0x10); // writes Old data to SRAM for programming
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataP[i]);
	}

	EPD_W21_WriteCMD(0x13); // writes New data to SRAM.
	for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
	{
		EPD_W21_WriteDATA(datas[i]);
		oldDataP[i] = datas[i];
	}
	EPD_Update();
	// Power_off();
}

// Partial refresh write address and data
void EPD_Dis_Part_RAM(unsigned int x_start, unsigned int y_start, const unsigned char *datas_A, const unsigned char *datas_B, const unsigned char *datas_C, const unsigned char *datas_D, const unsigned char *datas_E, unsigned char num, unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	unsigned int i, x_end, y_end;
	x_start = x_start - x_start % 8;
	x_end = x_start + PART_LINE - 1;
	y_end = y_start + PART_COLUMN * num - 1;

	EPD_Init_Part();
	EPD_W21_WriteCMD(0x91);		// This command makes the display enter partial mode
	EPD_W21_WriteCMD(0x90);		// resolution setting
	EPD_W21_WriteDATA(x_start); // x-start
	EPD_W21_WriteDATA(x_end);	// x-end

	EPD_W21_WriteDATA(y_start / 256);
	EPD_W21_WriteDATA(y_start % 256); // y-start

	EPD_W21_WriteDATA(y_end / 256);
	EPD_W21_WriteDATA(y_end % 256); // y-end
	EPD_W21_WriteDATA(0x01);

	if (partFlag == 1)
	{
		partFlag = 0;

		EPD_W21_WriteCMD(0x10); // writes Old data to SRAM for programming
		for (i = 0; i < PART_COLUMN * PART_LINE * num / 8; i++)
			EPD_W21_WriteDATA(0xFF);
	}
	else
	{
		EPD_W21_WriteCMD(0x10); // writes Old data to SRAM for programming
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataA[i]);
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataB[i]);
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataC[i]);
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataD[i]);
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataE[i]);
	}

	EPD_W21_WriteCMD(0x13); // writes New data to SRAM.
	{
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
		{
			EPD_W21_WriteDATA(datas_A[i]);
			oldDataA[i] = datas_A[i];
		}
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
		{
			EPD_W21_WriteDATA(datas_B[i]);
			oldDataB[i] = datas_B[i];
		}
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
		{
			EPD_W21_WriteDATA(datas_C[i]);
			oldDataC[i] = datas_C[i];
		}
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
		{
			EPD_W21_WriteDATA(datas_D[i]);
			oldDataD[i] = datas_D[i];
		}
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
		{
			EPD_W21_WriteDATA(datas_E[i]);
			oldDataE[i] = datas_E[i];
		}
	}
}
// Partial refresh write address and data
void EPD_Dis_Part_RAM2(unsigned int x_start, unsigned int y_start, const unsigned char *datas_A, const unsigned char *datas_B, unsigned char num, unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	unsigned int i, x_end, y_end;
	x_start = x_start - x_start % 8;
	x_end = x_start + PART_LINE - 1;
	y_end = y_start + PART_COLUMN * num - 1;

	EPD_Init_Part();
	EPD_W21_WriteCMD(0x91);		// This command makes the display enter partial mode
	EPD_W21_WriteCMD(0x90);		// resolution setting
	EPD_W21_WriteDATA(x_start); // x-start
	EPD_W21_WriteDATA(x_end);	// x-end

	EPD_W21_WriteDATA(y_start / 256);
	EPD_W21_WriteDATA(y_start % 256); // y-start

	EPD_W21_WriteDATA(y_end / 256);
	EPD_W21_WriteDATA(y_end % 256); // y-end
	EPD_W21_WriteDATA(0x01);

	if (partFlag == 1)
	{
		partFlag = 0;

		EPD_W21_WriteCMD(0x10); // writes Old data to SRAM for programming
		for (i = 0; i < PART_COLUMN * PART_LINE * num / 8; i++)
			EPD_W21_WriteDATA(0xFF);
		for (i = 0; i < PART_COLUMN * PART_LINE * num / 8; i++)
			EPD_W21_WriteDATA(0xFF);
	}
	else
	{
		EPD_W21_WriteCMD(0x10); // writes Old data to SRAM for programming
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataA[i]);
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataB[i]);
	}
	EPD_W21_WriteCMD(0x13); // writes New data to SRAM.
	{
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
		{
			EPD_W21_WriteDATA(datas_A[i]);
			oldDataA[i] = datas_A[i];
		}
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
		{
			EPD_W21_WriteDATA(datas_B[i]);
			oldDataB[i] = datas_B[i];
		}
	}
}
// Partial refresh write address and data
void EPD_Dis_Part_RAM3(unsigned int x_start, unsigned int y_start,
					   const unsigned char *datas_A, const unsigned char *datas_B,
					   unsigned char num, unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	unsigned int i, x_end, y_end;
	x_start = x_start - x_start % 8;
	x_end = x_start + PART_LINE - 1;
	y_end = y_start + PART_COLUMN * num - 1;

	EPD_Init_Part();
	EPD_W21_WriteCMD(0x91);		// This command makes the display enter partial mode
	EPD_W21_WriteCMD(0x90);		// resolution setting
	EPD_W21_WriteDATA(x_start); // x-start
	EPD_W21_WriteDATA(x_end);	// x-end

	EPD_W21_WriteDATA(y_start / 256);
	EPD_W21_WriteDATA(y_start % 256); // y-start

	EPD_W21_WriteDATA(y_end / 256);
	EPD_W21_WriteDATA(y_end % 256); // y-end
	EPD_W21_WriteDATA(0x01);

	if (partFlag2 == 1)
	{
		partFlag2 = 0;

		EPD_W21_WriteCMD(0x10); // writes Old data to SRAM for programming
		for (i = 0; i < PART_COLUMN * PART_LINE * num / 8; i++)
			EPD_W21_WriteDATA(0xFF);
		for (i = 0; i < PART_COLUMN * PART_LINE * num / 8; i++)
			EPD_W21_WriteDATA(0xFF);
	}
	else
	{
		EPD_W21_WriteCMD(0x10); // writes Old data to SRAM for programming
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataA2[i]);
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
			EPD_W21_WriteDATA(oldDataB2[i]);
	}
	EPD_W21_WriteCMD(0x13); // writes New data to SRAM.
	{
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
		{
			EPD_W21_WriteDATA(datas_A[i]);
			oldDataA2[i] = datas_A[i];
		}
		for (i = 0; i < PART_COLUMN * PART_LINE / 8; i++)
		{
			EPD_W21_WriteDATA(datas_B[i]);
			oldDataB2[i] = datas_B[i];
		}
	}
}
// Clock display
void EPD_Dis_Part_Time(unsigned int x_start, unsigned int y_start,
					   const unsigned char *datas_A, const unsigned char *datas_B,
					   const unsigned char *datas_C, const unsigned char *datas_D, const unsigned char *datas_E,
					   unsigned char num, unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	EPD_Dis_Part_RAM(x_start, y_start, datas_A, datas_B, datas_C, datas_D, datas_E, num, PART_COLUMN, PART_LINE);
	EPD_Update();
	// Power_off();
}

// Number display1
void EPD_Dis_Part_Num2(unsigned int x_start, unsigned int y_start,
					   const unsigned char *datas_A, const unsigned char *datas_B,
					   unsigned char num, unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	EPD_Dis_Part_RAM2(x_start, y_start, datas_A, datas_B, num, PART_COLUMN, PART_LINE);
	EPD_Update();
	// Power_off();
}
// Number display2
void EPD_Dis_Part_Num3(unsigned int x_start, unsigned int y_start,
					   const unsigned char *datas_A, const unsigned char *datas_B,
					   unsigned char num, unsigned int PART_COLUMN, unsigned int PART_LINE)
{
	EPD_Dis_Part_RAM3(x_start, y_start, datas_A, datas_B, num, PART_COLUMN, PART_LINE);
	EPD_Update();
	// Power_off();
}

////////////////////////////////Other newly added functions////////////////////////////////////////////
// Display rotation 180 degrees initialization
void EPD_Init_180(void)
{
	EPD_W21_RST_0; // Module reset
	delay_xms(10); // At least 10ms delay
	EPD_W21_RST_1;
	delay_xms(10); // At least 10ms delay

	EPD_W21_WriteCMD(0x00);
	EPD_W21_WriteDATA(0x1B); // 180 mirror

	EPD_W21_WriteCMD(0x04); // POWER ON
	delay_xms(300);
	lcd_chkstatus();

	EPD_W21_WriteCMD(0X50);	 // VCOM AND DATA INTERVAL SETTING
	EPD_W21_WriteDATA(0x97); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57		WBRmode:VBDF F7 VBDW 77 VBDB 37  VBDR B7
}

// GUI
void EPD_Init_GUI(void)
{
	EPD_W21_RST_0; // Module reset
	delay_xms(10); // At least 10ms delay
	EPD_W21_RST_1;
	delay_xms(10); // At least 10ms delay

	EPD_W21_WriteCMD(0x00);
	EPD_W21_WriteDATA(0x13);

	EPD_W21_WriteCMD(0x04); // Power on
	lcd_chkstatus();		// waiting for the electronic paper IC to release the idle signal

	EPD_W21_WriteCMD(0X50);	 // VCOM AND DATA INTERVAL SETTING
	EPD_W21_WriteDATA(0x97); // WBmode:VBDF 17|D7 VBDW 97 VBDB 57		WBRmode:VBDF F7 VBDW 77 VBDB 37  VBDR B7
}

#endif

/***********************************************************
						end file
***********************************************************/
